import numpy as np
from scipy import stats
import pandas as pd
import statsmodels.api as sm
import matplotlib.pyplot as plt
import os
import datetime
from sklearn.preprocessing import MinMaxScaler
import time
from statsmodels.tsa.stattools import adfuller


class Constant:
    sep = ','


def determine_d(timeseries):
    best_ts = 100000.0000
    for i in range(4):
        dftest = adfuller(timeseries, autolag='AIC')
        test_statistic = dftest[0]
        timeseries = timeseries.diff()
        if test_statistic < best_ts:
            best_ts = test_statistic
            d = i
    return d


def determine_pq(timeseries, bestd, exogx):
    pqmax = int(len(timeseries) / 10)
    bestbic = 1000000.0000
    for i in range(pqmax + 3):
        for m in range(pqmax + 3):
            try:
                bic = sm.tsa.ARIMA(dfy, (i, bestd, m), exog=exogx).fit(method="css-mle").bic
            except:
                continue
            if bic < bestbic:
                bestbic = bic
                p = i
                q = m
    return p, q


def recover_diff(trainseries, prediction, diffence):
    diff = [[]] * (diffence + 1)
    for i in range(1, diffence + 1):
        diff[0] = trainseries
        diff[i] = diff[i - 1].diff()

    diff_recover = [[]] * diffence
    a = range(diffence)
    for i in a[::-1]:
        pred_cumsum = prediction.cumsum()
        diff_recover[i] = pred_cumsum.add(diff[i][len(trainseries) - 1])
        prediction = diff_recover[i]
    return prediction


if __name__ == '__main__':
    dir_path = ["../data/sellout/weekly2", "../data/sellout/result_weekly"]
    files = os.listdir(dir_path[0])
    for file_name in files:
        file_path = dir_path[0] + "/" + file_name
        df = pd.read_csv(file_path, sep=Constant.sep)
        endog = df['quantity'].tolist()
        dfexog = df.loc[:, ['seasonality_na', 'seasonality_bestbuy']]
        exog = dfexog.values.tolist()
        s = MinMaxScaler().fit(exog)
        exogf = s.transform(exog)
        list_date = df['date'].tolist()
        i = 0
        dtall = sm.tsa.datetools.dates_from_str(list_date)
        list_date2 = []
        for i in range(len(list_date)):
            if '-' in list_date[i]:
                list_date2.append(datetime.datetime.strptime(list_date[i], '%Y-%m-%d').date())
            else:
                list_date2.append(datetime.datetime.strptime(list_date[i], '%Y/%m/%d').date())
        df['date'] = list_date2
        if file_name == "Flex-1470_sell_out_NA":
            z = 23
        elif file_name == "110S-11_sell_out_NA":
            z = 46
        else:
            z = 41
        for j in range(z, len(df) - 19):
            train_size = j
            test_size = 20
            dt = sm.tsa.datetools.dates_from_str(list_date[:train_size])
            start_date = list_date[train_size]
            end_date = list_date[train_size + test_size - 1]
            ytrain = endog[:train_size]
            s = MinMaxScaler().fit(ytrain)
            ytrainf = s.transform(ytrain)

            dfy = pd.TimeSeries(ytrainf, dt)
            dt2 = sm.tsa.datetools.dates_from_str(list_date)
            data = pd.TimeSeries(endog, dt2)
            exogx = np.array(exog[:train_size])
            s = MinMaxScaler().fit(exogx)
            exogxf = s.transform(exogx)
            endseq = train_size + test_size
            exogt = np.array(exog[train_size:endseq])
            s = MinMaxScaler().fit(exogt)
            exogtf = s.transform(exogt)
            d = determine_d(dfy)
            p, q = determine_pq(dfy, d, exogxf)
            print(p, d, q)
            fit2 = sm.tsa.ARIMA(dfy, (p, d, q), exog=exogxf).fit(method="css-mle")
            pred2 = fit2.predict(start=start_date, end=end_date, exog=exogtf, dynamic=False)
            pred2_shift = recover_diff(dfy, pred2, d)
            fieldp = "prediction_" + str(j)
            s = MinMaxScaler().fit(ytrain)
            pred2_df = pd.DataFrame({"date": pred2_shift.index.date, fieldp: s.inverse_transform(pred2_shift.values)})

            if j == z:
                df_result = df
            df_result = pd.merge(df_result, pred2_df, on='date', how='outer')

            plt.plot(pred2_df['date'], pred2_df[fieldp])
        df_result.to_csv(
            dir_path[1] + "/" + file_name + "_" + time.strftime('%m-%d', time.localtime(time.time())) + ".csv", sep=',')
        plt.plot(data.index.date, data)
        plt.grid(True)
        plt.title(file_name)
        plt.show()
        plt.close()
        df_result = pd.DataFrame
